﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Office.Interop.Outlook;
using Microsoft.SharePoint.Client;
using System.Net;
using AFS.VisitationRequestTool.Addin.Common;
using System.Windows.Forms;
using AFS.VisitationRequestTool.Addin.Variables;
using System.IO;
using AFS.VisitationRequestTool.Addin.Properties;
using System.Net.Cache;
using System.Security.Principal;

namespace AFS.VisitationRequestTool.Addin.Entities
{
    public class VisitationRequest
    {
        AppointmentItem appointmentItem;
        MeetingItem meetingItem;
        private Properties.Settings settings = new Properties.Settings();
        byte[] formData;
        string formName;

        int documentId;

        public string FormName
        {
            get
            {
                if (String.IsNullOrEmpty(formName))
                    formName = settings.FormLibraryPath + appointmentItem.Session.CurrentUser.Name + " - " + GetDocumentItemID() + ".xml"; // 
                return formName;
            }
            // set { formName = value; }
        }

        public byte[] FormData
        {
            get { return formData; }
            set { formData = value; }
        }

        public VisitationRequest(AppointmentItem appointmentItem)
        {
            this.appointmentItem = appointmentItem;
        }

        public VisitationRequest(MeetingItem meetingItem)
        {
            this.meetingItem = meetingItem;
        }

        public VisitationRequest()
        {
            // appointmentItem = (AppointmentItem)Globals.ThisAddIn.Application.ActiveInspector();
        }

        private void ClientContent_ExecutingWebRequest(object sender, WebRequestEventArgs e)
        {
            e.WebRequestExecutor.RequestKeepAlive = false;
            e.WebRequestExecutor.WebRequest.KeepAlive = false;
            e.WebRequestExecutor.WebRequest.CachePolicy = new RequestCachePolicy(RequestCacheLevel.NoCacheNoStore);
        }

        private string GetDocumentItemID()
        {
            ClientContext clientContext = new ClientContext(settings.SharePointSite);
            clientContext.ExecutingWebRequest += new EventHandler<WebRequestEventArgs>(ClientContent_ExecutingWebRequest);
            //Uri host = new Uri(settings.SharePointSite);

            ICredentials credentials = AFS.VisitationRequestTool.Addin.Common.Utility.GetCredentials();
            //NetworkCredential networkCreds = credentials.GetCredential(host, "Basic");
            //CredentialCache credentialCache = new CredentialCache();
            //credentialCache.Add(host, "Basic", networkCreds);          

            //new ClientContext("https://tssusa.accenture.com/sites/afs_visitation_tool_test");

            clientContext.Credentials = credentials; // credentialCache;

            List list = clientContext.Web.Lists.GetByTitle(settings.FormLibraryName);

            // CamlQuery camlQuery = CamlQuery.CreateAllItemsQuery(1, "ID");

            CamlQuery camlQuery = new CamlQuery();
            camlQuery.ViewXml = @"<View>
                                    <Query>
                                        <Where>
                                            <Eq>
                                                <FieldRef Name='FSObjType' />
                                                <Value Type='int'>0</Value>
                                            </Eq>
                                        </Where>
                                        <OrderBy><FieldRef Name='ID' Ascending='False'/></OrderBy>
                                    </Query>
                                    <RowLimit>1</RowLimit>
                                </View>";

            ListItemCollection itemCollection = list.GetItems(camlQuery);

            clientContext.Load(itemCollection);
            //WebRequestExecutor executor = clientContext.WebRequestExecutorFactory.CreateWebRequestExecutor(clientContext, "");
            //executor.WebRequest
            clientContext.ExecuteQuery();

            if (itemCollection.Count == 1)
            {
                documentId = (itemCollection[0].Id + 1);
            }
            else if (itemCollection.Count == 0)
                documentId = 1;
            else // How could this ever happen with row limit set to 1? (PA)
            {
                documentId = itemCollection.Max().Id;
            }

            clientContext.Dispose();

            return documentId.ToString();
        }

        // NOTE: this is a complete hack until find a way to switch user context back to logged in user upon creation
        private void UpdateCreatedByField()
        {
            ClientContext clientContext = new ClientContext(settings.SharePointSite);
            List visitationFormsList = clientContext.Web.Lists.GetByTitle(settings.FormLibraryName);
            ListItem visitationRequestItem = visitationFormsList.GetItemById(documentId);
            //FieldUserValue createdBy = visitationRequestItem["Created By"] as FieldUserValue;
            //FieldUserValue modifiedBy = visitationRequestItem["Modified By"] as FieldUserValue;

            User currentUser = clientContext.Web.EnsureUser(WindowsIdentity.GetCurrent().Name.ToUpper().Replace("AVANADE-CORP", "DIR"));
            visitationRequestItem["Author"] = currentUser;
            visitationRequestItem["Editor"] = currentUser;

            visitationRequestItem.Update();

            clientContext.ExecuteQuery();
        }

        public void UploadToVisitationRequestLibrary()
        {
            UploadToLibraryWithWebClientHelper();
            UpdateCreatedByField();
        }

        private void UploadToLibraryWithWebClientHelper()
        {
            if (formData.Length == 0)
            {
                throw new System.IO.FileLoadException("InfoPath form is empty.\nPlease refill form and retry submission.\nIf problem persist contact ithelp@accenturefederal.com");
            }

            // System.Security.Principal.WindowsIdentity identity = System.Security.Principal.WindowsIdentity.GetCurrent();
            // identity.Impersonate();
            // webClient.Credentials.GetCredential(new Uri(settings.FormLibraryPath + formName + ".xml"), "Basic");

            try
            {
                WebClient webClient = new WebClient();

                // webClient.Headers.Clear();
                // RequestCachePolicy cachePolicy = new RequestCachePolicy(RequestCacheLevel.NoCacheNoStore);
                // webClient.Credentials = new NetworkCredential("", "", "");  // System.Net.CredentialCache.DefaultNetworkCredentials; // AFS.VisitationRequestTool.Addin.Common.Utility.GetCredentials();

                webClient.Credentials = CredentialCache.DefaultNetworkCredentials;
                webClient.UseDefaultCredentials = true;
                // webClient.CachePolicy = cachePolicy;

                // AppDomain.CurrentDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal);
                //System.Security.Principal.WindowsImpersonationContext impersonationContext;
                //System.Security.Principal.WindowsIdentity

                //impersonationContext = WindowsIdentity.GetCurrent().Impersonate();
                //impersonationContext = ((System.Security.Principal.WindowsIdentity(WindowsIdentity.GetCurrent()).Impersonate());                    

                byte[] result = webClient.UploadData(this.FormName, "PUT", formData);

                //impersonationContext.Undo();

                // TODO: Implement result check and handler.
                string resultValue = System.Text.Encoding.ASCII.GetString(result);
                System.Diagnostics.Debug.WriteLine(resultValue);
            }
            catch (WebException ex)
            {
                Logger.Error(ex.ToString());
                MessageBox.Show(ErrorMessages.ProgramException);
            }
        }

        private void UploadToLibraryWithWebRequestHelper()
        {
            WebResponse response;
            WebRequest webRequest;

            webRequest = WebRequest.Create(formName);
            webRequest.UseDefaultCredentials = true;
            webRequest.Credentials = CredentialCache.DefaultCredentials;
            //webRequest.PreAuthenticate = true;
            //webRequest.ImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Impersonation;
            //webRequest.AuthenticationLevel = System.Net.Security.AuthenticationLevel.MutualAuthRequested;            

            if (formData.Length == 0)
            {
                throw new System.IO.FileLoadException("InfoPath form is empty.\nPlease refill form and retry submission.\nIf problem persist contact ithelp@accenturefederal.com");
            }

            webRequest.Method = "PUT";
            webRequest.ContentLength = formData.Length;

            Stream dataStream = webRequest.GetRequestStream();

            dataStream.Write(formData, 0, formData.Length);
            dataStream.Close();

            try
            {
                // TODO: Implement result check and handler.
                response = webRequest.GetResponse();
                // System.Diagnostics.Debug.WriteLine(resultValue);                
                response.Close();
            }
            catch (WebException ex)
            {
                Logger.Error(ex.ToString());
                MessageBox.Show(ErrorMessages.ProgramException);
            }
        }

        public String ValidateAppointment()
        {
            StringBuilder errors = new StringBuilder();

            // Checking if recurring b\c need to get dates from recurrence pattern properties if recurring appointment
            if (this.appointmentItem.IsRecurring)
            {
                if (Utility.GetDateTimeDifference(this.appointmentItem.GetRecurrencePattern().PatternStartDate, this.appointmentItem.GetRecurrencePattern().PatternEndDate) > 365)
                {
                    errors.AppendLine(ErrorMessages.ErrorMessageAppointmentCannotExceedOneYear);
                    errors.AppendLine();
                }

                if (this.appointmentItem.GetRecurrencePattern().NoEndDate)
                {
                    errors.AppendLine(ErrorMessages.ErrorMessageAppointmentMustHaveEndDate);
                    errors.AppendLine();
                }
            }
            else
            {
                if (Utility.GetDateTimeDifference(this.appointmentItem.Start, this.appointmentItem.End) > 365)
                {
                    errors.AppendLine(ErrorMessages.ErrorMessageAppointmentCannotExceedOneYear);
                    errors.AppendLine();
                }
            }

            return errors.ToString();
        }

    }
}
